ποΈGitΠ―ΡΠ°ποΈ
specs/006-kmp-project-structure/tasks.md bd2863243bab6eb213401d949839a2bc74dde7e2 (bd286324) Text, 19.04 KB
Tasks: KMP Recommended Project Structure Alignment
Input: Design documents from T383838/specs/006-kmp-project-structure/
Prerequisites: plan.md (required), spec.md (required for user stories), research.md, data-model.md, quickstart.md
Tests: No new automated tests are required by this specification. Validation is via existing build and test commands.
Verification: Every phase includes constitution-required validation tasks for formatting, static analysis, and the relevant compile/test commands.
Organization: Tasks are grouped by user story to enable independent implementation and testing. US4 (Legacy DSL Block Migration) is the primary implementation work, subdivided by migration tier.
Format: T383838[ID] [P?] [Story] Description
β’ [P]: Can run in parallel (different files, no dependencies)
β’ [Story]: Which user story this task belongs to (e.g., US1, US2, US3, US4)
β’ Include exact file paths in descriptions
Phase 1: Setup (Baseline & Prerequisites)
Purpose: Establish a clean build baseline and verify the starting state before any changes
β’ [ ] T001 Verify clean build baseline by running T383838./gradlew assembleDebug :desktop:packageUberJarForCurrentOS allTests and record clean T383838assembleDebug wall-clock time (3 consecutive runs after T383838./gradlew clean, median value) to T383838specs/006-kmp-project-structure/baseline-timing.txt for NFR-001 comparison
β’ [ ] T002 Verify T383838DESKTOP_ONLY=true ./gradlew :desktop:packageUberJarForCurrentOS passes before migration
β’ [x] T003 Run T383838grep -rn "android {" core/*/build.gradle.kts feature/*/build.gradle.kts to document all 27 legacy T383838android {} blocks as the pre-migration inventory
Phase 2: Convention Plugin Hardening (US2 β Blocking Prerequisite)
Purpose: Harden convention plugin defaults so modules can rely on convention for T383838androidResources.enable = false. This MUST complete before any module migration.
Goal: Convention plugins reflect recommended patterns β T383838configureKotlinMultiplatform() absorbs the T383838androidResources.enable = false default so 23 of 27 modules no longer need to set it explicitly.
β οΈ CRITICAL: No module migration (Phase 3β5) can begin until this phase is complete.
Independent Test: T383838./gradlew assembleDebug passes β adding the default is backward-compatible since all modules currently override it.
β’ [x] T004 [US2] Add T383838androidResources.enable = false default to T383838configureKotlinMultiplatform() inside the T383838pluginManager.withPlugin block in T383838build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt (add after T383838minSdk assignment, before namespace auto-derivation)
β’ [x] T005 [US2] Verify convention plugin change builds successfully: T383838./gradlew assembleDebug :desktop:packageUberJarForCurrentOS allTests
Checkpoint: Convention plugin hardened β module migration can now begin
Phase 3: Tier 1 Module Migration β Simple Modules (US4, Priority: P1) π― MVP
Goal: Migrate 6 modules where convention handles everything β remove T383838android {} block entirely, remove redundant T383838jvm() declarations, remove explicit T383838namespace (auto-derived), remove T383838androidResources.enable = false (convention default).
Independent Test: T383838./gradlew assembleDebug allTests passes after all 6 modules migrated. Verify with T383838grep -rn "android {" core/di/build.gradle.kts core/nfc/build.gradle.kts core/ui/build.gradle.kts core/navigation/build.gradle.kts feature/settings/build.gradle.kts feature/messaging/build.gradle.kts returning zero matches.
Implementation for Tier 1
β’ [x] T006 [P] [US4] Migrate T383838core/di/build.gradle.kts β remove T383838android {} block (namespace auto-derived, resources disabled by convention), remove redundant T383838jvm() if present
β’ [x] T007 [P] [US4] Migrate T383838core/nfc/build.gradle.kts β remove T383838android {} block (namespace auto-derived, resources disabled by convention)
β’ [x] T008 [P] [US4] Migrate T383838core/ui/build.gradle.kts β remove T383838android {} block (namespace auto-derived, resources disabled by convention), remove redundant T383838jvm() if present
β’ [x] T009 [P] [US4] Migrate T383838core/navigation/build.gradle.kts β remove T383838android {} block (namespace auto-derived)
β’ [x] T010 [P] [US4] Migrate T383838feature/settings/build.gradle.kts β remove T383838android {} block (namespace auto-derived, resources disabled by convention)
β’ [x] T011 [P] [US4] Migrate T383838feature/messaging/build.gradle.kts β remove T383838android {} block (namespace auto-derived, resources disabled by convention)
β’ [x] T012 [US4] Verify Tier 1 batch: T383838./gradlew assembleDebug allTests β commit must be independently buildable (NFR-003)
Checkpoint: Tier 1 complete β 6 of 27 modules migrated, build passes
Phase 4: Tier 2 Module Migration β Standard Modules with Host Tests (US4, Priority: P1)
Goal: Migrate 18 modules that opt into T383838withHostTest {}. Replace T383838android {} with T383838androidLibrary { withHostTest {} }, remove redundant T383838jvm(), remove explicit T383838namespace (auto-derived except T383838feature:wifi-provision), remove T383838androidResources.enable = false (convention default).
Independent Test: T383838./gradlew assembleDebug :desktop:packageUberJarForCurrentOS allTests passes after all 18 modules migrated.
Tier 2a: Modules with T383838withHostTest { isIncludeAndroidResources = true } (13 modules)
β’ [x] T013 [P] [US4] Migrate T383838core/ble/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove redundant T383838jvm(), remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T014 [P] [US4] Migrate T383838core/common/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove redundant T383838jvm(), remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T015 [P] [US4] Migrate T383838core/data/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove redundant T383838jvm(), remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T016 [P] [US4] Migrate T383838core/domain/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove redundant T383838jvm(), remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T017 [P] [US4] Migrate T383838core/model/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove redundant T383838jvm(), remove T383838androidResources.enable = false
β’ [x] T018 [P] [US4] Migrate T383838core/network/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove redundant T383838jvm(), remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T019 [P] [US4] Migrate T383838core/service/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T020 [P] [US4] Migrate T383838core/takserver/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove redundant T383838jvm(), remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T021 [P] [US4] Migrate T383838feature/connections/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T022 [P] [US4] Migrate T383838feature/firmware/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T023 [P] [US4] Migrate T383838feature/intro/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T024 [P] [US4] Migrate T383838feature/map/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove redundant T383838jvm(), remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T025 [P] [US4] Migrate T383838feature/node/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true } }, remove explicit namespace, remove T383838androidResources.enable = false
Tier 2b: Modules with empty T383838withHostTest {} (4 modules)
β’ [x] T026 [P] [US4] Migrate T383838core/datastore/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest {} }, remove redundant T383838jvm(), remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T027 [P] [US4] Migrate T383838core/prefs/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest {} }, remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T028 [P] [US4] Migrate T383838core/repository/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest {} }, remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T029 [P] [US4] Migrate T383838core/testing/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest {} }, remove explicit namespace, remove T383838androidResources.enable = false
Tier 2c: Namespace override required (1 module)
β’ [x] T030 [P] [US4] Migrate T383838feature/wifi-provision/build.gradle.kts β replace T383838android {} with T383838androidLibrary { namespace = "org.meshtastic.feature.wifiprovision"; withHostTest {} }, remove redundant T383838jvm(), remove T383838androidResources.enable = false (namespace MUST be explicit β auto-derived T383838feature.wifi.provision differs from required T383838feature.wifiprovision)
Tier 2 Verification
β’ [x] T031 [US4] Verify Tier 2 batch: T383838./gradlew assembleDebug :desktop:packageUberJarForCurrentOS allTests and T383838DESKTOP_ONLY=true ./gradlew :desktop:packageUberJarForCurrentOS β commit must be independently buildable (NFR-003)
Checkpoint: Tiers 1 + 2 complete β 24 of 27 modules migrated, build passes
Phase 5: Tier 3 Module Migration β Special Modules (US4, Priority: P1)
Goal: Migrate 3 modules with custom configuration (minSdk override, device tests, resource prefix).
Independent Test: T383838./gradlew assembleDebug :desktop:packageUberJarForCurrentOS allTests passes. All special configurations preserved.
Implementation for Tier 3
β’ [x] T032 [P] [US4] Migrate T383838core/proto/build.gradle.kts β replace T383838android {} with T383838androidLibrary { minSdk = 21 } (ATAK compatibility override), remove T383838androidResources.enable = false
β’ [x] T033 [P] [US4] Migrate T383838core/database/build.gradle.kts β replace T383838android {} with T383838androidLibrary { withHostTest { isIncludeAndroidResources = true }; withDeviceTest { instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } }, remove explicit namespace, remove T383838androidResources.enable = false
β’ [x] T034 [P] [US4] Migrate T383838core/resources/build.gradle.kts β replace T383838android {} with T383838androidLibrary { androidResources { enable = true; resourcePrefix = "meshtastic_" }; withHostTest { isIncludeAndroidResources = true } }, remove redundant T383838jvm() (resources MUST override convention default to T383838enable = true)
β’ [x] T035 [US4] Verify Tier 3 batch: T383838./gradlew assembleDebug :desktop:packageUberJarForCurrentOS allTests β commit must be independently buildable (NFR-003)
Checkpoint: All 27 KMP modules migrated β zero legacy T383838android {} blocks remain
Phase 6: Full Verification & Build Validation (US1, Priority: P1)
Goal: Developer builds successfully after restructuring β full verification across all build modes and configurations.
Independent Test: All 4 acceptance scenarios from US1 pass.
β’ [ ] T036 [US1] Run full Android build: T383838./gradlew assembleDebug β verify zero errors
β’ [ ] T037 [US1] Run full Desktop build: T383838./gradlew :desktop:packageUberJarForCurrentOS β verify zero errors
β’ [ ] T038 [US1] Run all tests: T383838./gradlew allTests β verify zero regressions
β’ [ ] T039 [US1] Run DESKTOP_ONLY mode: T383838DESKTOP_ONLY=true ./gradlew :desktop:packageUberJarForCurrentOS β verify succeeds without Android SDK
β’ [ ] T040 [US1] Compare clean T383838assembleDebug time against baseline from T001 (3 consecutive runs after T383838./gradlew clean, median value, same machine) β verify <5% increase (NFR-001)
Checkpoint: US1 complete β all build modes verified
Phase 7: Polish & Cross-Cutting Concerns
Purpose: Final validation, cleanup, and constitution compliance
β’ [x] T041 [P] Verify no legacy T383838android {} blocks remain: T383838grep -rn "android {" core/*/build.gradle.kts feature/*/build.gradle.kts | grep -v "widget\|api\|barcode\|androidLibrary\|androidResources\|androidMain\|androidHostTest\|androidDeviceTest\|androidRuntimeClasspath" β must return zero matches (SC-001)
β’ [x] T042 [P] Verify no redundant T383838jvm() calls remain in migrated modules: T383838grep -n "jvm()" core/*/build.gradle.kts feature/*/build.gradle.kts | grep -v "widget\|api\|barcode" β must return zero matches
β’ [x] T043 [P] Verify T383838configureKotlinMultiplatform() in T383838build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt uses only T383838KotlinMultiplatformAndroidLibraryTarget API β no legacy T383838android {} extension configuration (SC-007)
β’ [x] T044 [P] [US3] Verify module dependency direction is preserved: no T383838core/ module depends on T383838feature/ modules (FR-006)
β’ [x] T045 [P] Run constitution-required verification: T383838./gradlew spotlessApply spotlessCheck detekt
β’ [x] T046 [P] Verify Gradle configuration cache, isolated projects, and parallel execution remain functional (NFR-002): T383838./gradlew assembleDebug --configuration-cache
β’ [ ] T047 Validate quickstart.md in T383838specs/006-kmp-project-structure/quickstart.md matches final implementation β update if migration steps differ from what was executed. Ensure guide is generic enough for other Meshtastic platform repos to reference (NFR-004)
β’ [x] T048 [US2] Add FR-008 enforcement: add a CI-time grep check in Phase 7 verification or a Gradle T383838afterEvaluate assertion in T383838configureKotlinMultiplatform() that fails the build if any KMP module contains a legacy T383838android {} block inside T383838kotlin {} β prevents future regressions (FR-008)
β’ [ ] T049 [P] Verify SC-006: create a temporary scratch module applying T383838meshtastic.kmp.library, confirm it configures correctly for Android + Desktop with no manual T383838android {} block, then remove it
Dependencies & Execution Order
Phase Dependencies
β’ Setup (Phase 1): No dependencies β can start immediately
β’ Convention Plugin Hardening (Phase 2): Depends on Phase 1 β BLOCKS all module migrations
β’ Tier 1 Migration (Phase 3): Depends on Phase 2 completion
β’ Tier 2 Migration (Phase 4): Depends on Phase 2 completion (can run in parallel with Phase 3)
β’ Tier 3 Migration (Phase 5): Depends on Phase 2 completion (can run in parallel with Phases 3β4)
β’ Full Verification (Phase 6): Depends on Phases 3, 4, and 5 completion
β’ Polish (Phase 7): Depends on Phase 6 completion
User Story Dependencies
β’ US2 (Convention Plugins): Phase 2 β Must complete first; blocking prerequisite
β’ US4 (Legacy DSL Migration): Phases 3, 4, 5 β Primary implementation; depends on US2
β’ US1 (Build Verification): Phase 6 β Validation of US4 work; depends on all tiers complete
β’ US3 (Module Boundary Clarity): Verified in Phase 7 (T044) β no implementation needed, existing structure already satisfies
Within Each Tier
β’ All module migrations within a tier marked [P] can run in parallel (different files, no dependencies)
β’ Tier verification task must run after all module tasks in that tier complete
β’ Tiers 1, 2, and 3 can themselves run in parallel after Phase 2 completes
Parallel Opportunities
β’ Phase 2: Sequential (single file change + verification)
β’ Phase 3: T006βT011 all parallel (6 different T383838build.gradle.kts files)
β’ Phase 4: T013βT030 all parallel (18 different T383838build.gradle.kts files)
β’ Phase 5: T032βT034 all parallel (3 different T383838build.gradle.kts files)
β’ Phase 7: T041βT046 all parallel (independent verification commands)
β’ Cross-tier: Phases 3, 4, 5 can all run in parallel after Phase 2
Parallel Example: Tier 1 Migration
T282828
T006: core/di/build.gradle.kts
T007: core/nfc/build.gradle.kts
T008: core/ui/build.gradle.kts
T009: core/navigation/build.gradle.kts
T010: feature/settings/build.gradle.kts
T011: feature/messaging/build.gradle.kts
T012: ./gradlew assembleDebug allTests
Parallel Example: Full Tier Parallelism
T282828
Tier 1 (T006βT012): 6 simple modules β remove android {} entirely
Tier 2 (T013βT031): 18 standard modules β replace with androidLibrary { withHostTest {} }
Tier 3 (T032βT035): 3 special modules β custom config (minSdk, device tests, resources)
Implementation Strategy
MVP First (Tier 1 Only)
1. Complete Phase 1: Setup (baseline)
2. Complete Phase 2: Convention plugin hardening (T004βT005)
3. Complete Phase 3: Tier 1 β 6 simple modules (T006βT012)
4. STOP and VALIDATE: Build passes, 6 modules proven
5. This alone demonstrates the migration pattern works
Incremental Delivery
1. Setup + Convention Plugin Hardening β Foundation ready
2. Tier 1 (6 modules) β Build verified β Pattern proven (MVP!)
3. Tier 2 (18 modules) β Build verified β Bulk migration complete
4. Tier 3 (3 modules) β Build verified β All 27 modules done
5. Full verification + polish β Ready for PR
Key Risk Mitigation
β’ Each tier is independently verifiable β if Tier 2 breaks, Tier 1 is still valid
β’ Convention plugin change (T004) is backward-compatible β existing explicit overrides in modules are no-ops
β’ Individual module migrations can be reverted independently (T383838git checkout -- <module>/build.gradle.kts)
β’ T383838feature:wifi-provision is the only namespace edge case β flagged explicitly in T030
Notes
β’ [P] tasks = different files, no dependencies on each other
β’ [US4] is the primary user story β all module migration tasks belong to it
β’ No source code files are modified β only T383838build.gradle.kts files and one convention plugin T383838.kt file
β’ The spec lists 28 modules but T383838core:model was counted in both research.md Tier 1 and data-model.md Tier 2 β data-model.md (Tier 2 with T383838withHostTest) is authoritative, yielding 27 total KMP modules
β’ T383838feature:widget, T383838core:api, T383838core:barcode are Android-only and NOT affected by this migration
β’ Commit after each tier verification for clean rollback points
Served by rngit 1.5.0 - Generated in 0.04s